<template>
  <div class="x6-graph">
    <el-button v-if="type === 'view'" class="edit-btn" type="primary" size="mini" @click="goEdit">
      编辑
    </el-button>
    <div id="container" />
  </div>
</template>
<script>
import { Graph, Shape } from '@antv/x6'
import { Transform } from '@antv/x6-plugin-transform'
import { Selection } from '@antv/x6-plugin-selection'
import { Snapline } from '@antv/x6-plugin-snapline'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Clipboard } from '@antv/x6-plugin-clipboard'
import { History } from '@antv/x6-plugin-history'
import { register } from '@antv/x6-vue-shape'
import ProgressNode from './customNodesVue/progress.vue'
import SensorNode from './customNodesVue/sensor.vue'
import CustomTableNode from './customNodesVue/customTable.vue'
export default {
  props: {
    type: {
      type: String,
      default: 'view'
    }
  },
  data () {
    return {
      graph: null
    }
  },
  mounted () {
    this.initGraph()
    if (this.type === 'edit') {
      this.usePluging()
      this.graphMethods()
      this.graphEvents()
    }
    this.registerCustomVueNode()
    this.initDate()
  },
  methods: {
    // 初始化画布
    initGraph () {
      let config = {}
      if (this.type === 'view') {
        config = {
          grid: true,
          panning: {
            enabled: true,
            eventTypes: ['leftMouseDown', 'mouseWheel']
          },
          mousewheel: {
            enabled: true,
            zoomAtMousePosition: true,
            modifiers: 'ctrl',
            minScale: 0.1,
            maxScale: 2
          },
          interacting: false
        }
      } else if (this.type === 'edit') {
        config = {
          grid: true,
          panning: {
            enabled: true,
            eventTypes: ['leftMouseDown', 'mouseWheel']
          },
          mousewheel: {
            enabled: true,
            zoomAtMousePosition: true,
            modifiers: 'ctrl',
            minScale: 0.1,
            maxScale: 3
          },
          connecting: {
            router: 'manhattan',
            connector: {
              name: 'rounded',
              args: {
                radius: 8
              }
            },
            anchor: 'center',
            connectionPoint: 'anchor',
            allowBlank: false,
            snap: {
              radius: 20
            },
            createEdge () {
              return new Shape.Edge({
                attrs: {
                  line: {
                    stroke: '#A2B1C3',
                    strokeWidth: 2,
                    targetMarker: {
                      name: 'block',
                      width: 12,
                      height: 8
                    }
                  }
                },
                zIndex: 0
              })
            },
            validateConnection ({ targetMagnet }) {
              return !!targetMagnet
            }
          },
          highlighting: {
            magnetAdsorbed: {
              name: 'stroke',
              args: {
                attrs: {
                  fill: '#5F95FF',
                  stroke: '#5F95FF'
                }
              }
            }
          },
          interacting: (cellView) => {
            if (cellView.cell.id === 'backgroundNode') {
              return false
            }
            return true
          }
        }
      }

      this.$store.state.graphStore.graph = this.graph = new Graph({
        container: document.getElementById('container'),
        ...config
      })
    },
    // 加入插件
    usePluging () {
      this.graph
        .use(
          new Transform({
            resizing: {
              enabled: (node) => {
                if (node.id === 'backgroundNode') {
                  return false
                }
                return true
              }
            },
            rotating: {
              enabled: (node) => {
                if (node.id === 'backgroundNode') {
                  return false
                }
                return true
              }
            }
          })
        )
        .use(new Selection({
          rubberband: false,
          showNodeSelectionBox: true
        }))
        .use(new Snapline())
        .use(new Keyboard())
        .use(new Clipboard())
        .use(new History())
    },
    // 画布方法
    graphMethods () {
      // 复制
      this.graph.bindKey(['meta+c', 'ctrl+c'], () => {
        const cells = this.graph.getSelectedCells()
        if (cells.length) {
          this.graph.copy(cells)
        }
        return false
      })
      // 粘贴
      this.graph.bindKey(['meta+v', 'ctrl+v'], () => {
        if (!this.graph.isClipboardEmpty()) {
          const cells = this.graph.paste({ offset: 32 })
          this.graph.cleanSelection()
          this.graph.select(cells)
        }
        return false
      })
      // 上一步
      this.graph.bindKey(['meta+z', 'ctrl+z'], () => {
        if (this.graph.canUndo()) {
          this.graph.undo()
        }
        return false
      })
      // 下一步
      this.graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
        if (this.graph.canRedo()) {
          this.graph.redo()
        }
        return false
      })
      // 删除
      this.graph.bindKey(['backspace', 'delete'], () => {
        const cells = this.graph.getSelectedCells()
        if (cells.length) {
          this.graph.removeCells(cells)
        }
      })
      // 保存
      this.graph.bindKey(['meta+shift+s', 'ctrl+shift+s'], () => {
        const drawJson = JSON.stringify(this.graph.toJSON())
        this.$http.post('/monitor/draw/saveOrUpdateDraw', {
          customerNo: this.$route.query.customerNo,
          drawJson
        })
      })
    },
    // 画布事件
    graphEvents () {
      this.graph.on('history:change', () => {
        this.$store.commit('SET_HISTORY_CAN_REDO', this.graph.canRedo()) // 是否有下一步
        this.$store.commit('SET_HISTORY_CAN_UNDO', this.graph.canUndo()) // 是否有上一步
      })
      this.graph.on('cell:selected', (e) => {
        // 背景不编辑
        if (e.cell.shape === 'background-node') {
          return this.graph.unselect(e.cell)
        }
        this.$store.commit('SET_SELECTED', e.cell)
      })
      this.graph.on('cell:unselected', (e) => {
        this.$store.commit('REMOVE_SELECTED')
      })
    },
    // 注册自定义节点
    registerCustomVueNode () {
      register({
        shape: 'vue-progress',
        width: 100,
        height: 100,
        component: ProgressNode
      })
      register({
        shape: 'vue-sensor',
        width: 100,
        height: 80,
        component: SensorNode
      })
      register({
        shape: 'vue-customTable',
        width: 100,
        height: 100,
        component: CustomTableNode
      })
      Graph.registerNode(
        'background-node',
        {
          width: 200,
          height: 200,
          zIndex: 0,
          attrs: {
            image: {
              'xlink:href': ''
            }
          },
          markup: [
            {
              tagName: 'image',
              selector: 'image',
              style: {
                cursor: 'grab'
              }
            }
          ]
        },
        true
      )
    },
    // 初始化数据
    async initDate () {
      await this.$store.dispatch('getSensorList')
      // 获取graph数据
      const res = await this.$http.get(`/monitor/draw/getDraw?customerNo=${this.$route.query.customerNo}`)
      if (res.length) {
        const drawJson = JSON.parse(res[0].drawJson)
        this.$store.commit('SET_DOWNLOAD_ID', res[0].downloadId)
        this.graph.fromJSON(drawJson)
        this.graph.zoomToFit({ maxScale: 1.6 })
        this.graph.centerContent()
      }
      // 获取传感器数据
      setInterval(() => {
        this.$store.dispatch('getSensorList')
      }, 10000)
    },
    goEdit () {
      this.$router.push(`/editor?customerNo=${this.$route.query.customerNo}`)
    }
  }
}
</script>
<style lang="scss" scoped>
.x6-graph {
  flex: 1;
  order: 2;
  .edit-btn{
    position: absolute;
    right: 10px;
    bottom: 10px;
    z-index: 9;
  }

  #container {
    width: 100%;
    height: 100%;
  }
}
</style>
